package com.zhangc.limiter;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.cache.Cache;
import com.zhangc.zcscm.client.SCMClientImpl;
import com.zhangc.zcscm.client.SCMListener;
import com.zhangc.zcscm.client.SCMNode;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 17040686
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class FilterScmUtilHelper {
    private static SCMNode snsisScmNode;
    private static String SCHEDULE_TIME = "scheduleTime";
    private static String MAX_CACHE_SIZE = "maxCacheSize";

    private static Properties props = new Properties();

    public static final Logger LOGGER = LoggerFactory.getLogger(FilterScmUtilHelper.class);

    /**
     * scm 节点名
     */
    public static final String SNSISPROPERTIES = "rateLimit.properties";

    static {
        getSCMMessage();
    }

    /**
     * 工具类隐藏公共构造方法
     */
    private FilterScmUtilHelper() {
    }

    public static String getValueByKey(String key) {
        if (snsisScmNode == null) {
            getSCMMessage();
        }
        return props.getProperty(key);
    }

    @SuppressWarnings("deprecation")
    public static void getSCMMessage() {
        try {
            // 获取节点
            snsisScmNode = SCMClientImpl.getInstance().getConfig(SNSISPROPERTIES);
            snsisScmNode.sync();
            snsisScmNode.monitor(new SCMListener() {
                @Override
                public void execute(String oldValue, String newValue) {
                    setSCMListener(oldValue, newValue);
                }
            });
            String txt = snsisScmNode.getValue();
            StringReader reader = new StringReader(txt);
            props.load(reader);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("SCM初始化转码发生异常", e);
        } catch (Exception e) {
            LOGGER.error("SCM初始化获取节点异常", e);
        }
    }

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param oldValue
     * @param newValue
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void setSCMListener(String oldValue, String newValue) {
        String txt = snsisScmNode.getValue();
        // 解决当整个节点先删除，再添加，监听器失效bug
        if (txt == null) {
            snsisScmNode = null;
            return;
        }
        try (StringReader reader = new StringReader(txt)) {
            props = new Properties();
            props.load(reader);
            // 检查SCHEDULE_TIME和MAX_CACHE_SIZE是否有变化
            checkGlobal(oldValue, newValue);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("SCM配置发生更改，转码发生异常", e);
        } catch (IOException e) {
            LOGGER.error("SCM配置发生更改，获取节点异常", e);
        }
    }

    /**
     * 功能描述:检查全局变量 <br>
     * 〈功能详细描述〉
     *
     * @param oldValue
     * @param newValue
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void checkGlobal(String oldValue, String newValue) {
        try {
            Properties propsOld = new Properties();
            Properties propsNew = new Properties();
            propsOld.load(new StringReader(oldValue));
            propsNew.load(new StringReader(newValue));
            // 检查SCHEDULE_TIME和MAX_CACHE_SIZE是否有变化
            String scheduleTimeOld = propsOld.getProperty(SCHEDULE_TIME);
            String scheduleTimeNew = propsNew.getProperty(SCHEDULE_TIME);
            String maxCacheSizeOld = propsOld.getProperty(MAX_CACHE_SIZE);
            String maxCacheSizeNew = propsNew.getProperty(MAX_CACHE_SIZE);
            if ((!scheduleTimeOld.equals(scheduleTimeNew) || !maxCacheSizeOld.equals(maxCacheSizeNew))
                    && StringUtils.isNotBlank(scheduleTimeNew) && StringUtils.isNotBlank(maxCacheSizeNew)) {
                // 情况全部缓存
                Cache<String, AtomicInteger> accountCounterCache = RateLimiterFilter.getAccountCounterCache();
                if (accountCounterCache != null) {
                    accountCounterCache.invalidateAll();
                }
                // 创建新的缓存仓库
                RateLimiterFilter.setAccountCounterCache(scheduleTimeNew, maxCacheSizeNew);
            }
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("SCM配置发生更改，转码发生异常", e);
        } catch (Exception e) {
            LOGGER.error("SCM配置发生更改，获取节点异常", e);
        }
    }
}
